package com.xxxx.paipaicars.config.auth_phase;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xxxx.paipaicars.bean.UserDO;
import com.xxxx.paipaicars.bean.dto.UserDTO;
import com.xxxx.paipaicars.common.CommonConstant;
import com.xxxx.paipaicars.dao.UserMapper;
import com.xxxx.paipaicars.utils.JwtOperator;
import com.xxxx.paipaicars.utils.RedisUtil;
import com.xxxx.paipaicars.utils.SpringUtil;
import com.xxxx.paipaicars.utils.ThreadLocalUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

/**
 * @author 北海不是海
 * @version 1.0
 * Create by 2023-06-11 21:37
 * 普通用户接口
 */

public class UserAccessPhase implements ICommonAccessPhase{

    @Resource
    private JwtOperator jwtOperator;

    @Resource
    private UserMapper userMapper;

    private static final Logger logger = LoggerFactory.getLogger(UserAccessPhase.class);

    //TODO:该方法用于 普通用户登入的时候 对其Token等必要进行进行校验
    @Override
    public Boolean accessPhase(HttpServletRequest request, HttpServletResponse response) {
        RedisUtil redisUtil = SpringUtil.getBean("RedisUtil");
        //从http头部获取对应的toke
        String token = request.getHeader("token");
        if(StringUtils.isBlank(token)){
            logger.warn("token信息");
            return false;
        }

        //说明存在token 对Token的非法性进行校验
        Boolean validateToken = jwtOperator.validateToken(token);
        if(!validateToken){
            logger.warn("您的Token已过期");
            return false;
        }
        //获取用户信息
        String phoneNumber = jwtOperator.getClaimsFromToken(token).get(CommonConstant.PHONE_NUMBER).toString();
        //进行和缓存进行对比
        String redisToken = redisUtil.get(CommonConstant.TOKEN_PREFIX + phoneNumber);
        if(!redisToken.equals(token)){
            logger.warn("非法的token信息");
            return false;
        }

        // 从token拿到用户原信息,存储需要使用的业务信息放到线程中
        // 从redis中查询(数据库 ---> redis),如果有直接放到线程中,如果没有,查询数据库同时放入到缓存和线程中
        String userInfoCache = CommonConstant.REDIS_USER_INFO_CACHE + phoneNumber;
        String ThreadKey = CommonConstant.THREAD_LOCAL_USER_INFO + phoneNumber;
        if(redisUtil.hasKey(userInfoCache)){
            //通过缓存获取到用户数据 存入到当前线程
            //进行数据序列化
            UserDTO userDTO = JSON.parseObject(redisUtil.get(userInfoCache),UserDTO.class);
            //存入线程去
            ThreadLocalUtil.set(ThreadKey,userDTO);
        }

        //若缓存没有 则进入到数据库去取
        UserDO dbUserDO = userMapper.selectOne(new LambdaQueryWrapper<UserDO>()
                .eq(UserDO::getPhoneNumber, phoneNumber));

        if (Objects.isNull(dbUserDO)) {
            logger.error("用户: {} 信息不存在", phoneNumber);
            return false;
        }

        // 放入到缓存中
        redisUtil.set(userInfoCache, com.alibaba.fastjson.JSON.toJSONString(dbUserDO));
        ThreadLocalUtil.set(ThreadKey, dbUserDO);

        return true;
    }
}
